﻿

using IotClientService.Handles;
using IotClientService.Handles.lgs;
using IotClientService.Models.Lg;
using IotContract.Dtos.Clients.Equips;
using IotContract.Dtos.Servers;
using IotContract.Events;
using IotContract.Interfaces;
using IotContract.Models.Clients;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using XT.Common.Extensions;
using XT.Common.Services;

namespace IotClientService.Operations.hk.Lg;
public class LgHkOperation : IEquipOperation<LgHkEquipDto>
{
    
    private bool _status = false;
    private LgTcpState _tcpState;
    private LgHkEquipDto _equipInfo;
    private LgHandleBase _lgEquipHandle;
    // tcp服务发送
    private LgTcpServerHandle _tcpServerSendHandle;
    private IServiceProvider _provider;
    private CancellationTokenSource _cancellationTokenSource;
    // tcp服务接收
    private LgTcpServerHandle _tcpServerReceiveHandle;
    private ILogService _logService;


    public event EventHandler<ConnectStatusEventArgs> OnConnectStatusChanged;

    public LgHkOperation(IServiceProvider provider, ILogService logService)
    {
        _logService = logService;
        _provider = provider;
        _tcpServerSendHandle = new LgTcpServerHandle();
       
        _tcpServerSendHandle.ConnectionRequestEvent += _tcpServerSendHandle_ConnectionRequestEvent;
        _tcpServerSendHandle.RecievedEvent += _tcpServerSendHandle_RecievedEvent;
        _tcpServerSendHandle.StateChangeEvent += _tcpServerSendHandle_StateChangeEvent;

        _tcpServerReceiveHandle = new LgTcpServerHandle();
        _tcpServerReceiveHandle.ConnectionRequestEvent += _tcpServerReceiveHandle_ConnectionRequestEvent;
        _tcpServerReceiveHandle.RecievedEvent += _tcpServerReceiveHandle_RecievedEvent;
        _tcpServerReceiveHandle.StateChangeEvent += _tcpServerReceiveHandle_StateChangeEvent;
    }

    private async void _tcpServerReceiveHandle_StateChangeEvent(object? sender, LgTcpState e)
    {
        _tcpState = e;
        _equipInfo.Remark = _tcpState.ToString();
        // 5s进行重连
        if (_tcpState == LgTcpState.Closed && _status == true)
        {
            OnConnectStatusChanged?.Invoke(this, new ConnectStatusEventArgs
            {
                Connect = GetConnection(),
                IsSuccess = false,
                Message = "服务掉线，重新建立服务"
            });
            _cancellationTokenSource.Cancel();
            await Task.Delay(5000);
           
            await OperationStart();
        }
    }

    /// <summary>
    /// 数据发送客户端建立连接
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void _tcpServerReceiveHandle_ConnectionRequestEvent(object? sender, Socket e)
    {
        _tcpServerReceiveHandle.AddAccept(e);
    }


    /// <summary>
    /// 状态改变事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <exception cref="NotImplementedException"></exception>
    private async void _tcpServerSendHandle_StateChangeEvent(object? sender, LgTcpState e)
    {
        _tcpState = e;
        _equipInfo.Remark = _tcpState.ToString();
        // 5s进行重连
        if (_tcpState==LgTcpState.Closed && _status==true)
        {
            OnConnectStatusChanged?.Invoke(this, new ConnectStatusEventArgs
            {
                Connect = GetConnection(),
                IsSuccess = false,
                Message = "服务掉线，重新建立服务"
            });
            _cancellationTokenSource.Cancel();
            await Task.Delay(5000);

            await OperationStart();
        }
    }

    /// <summary>
    /// 数据接收事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <exception cref="NotImplementedException"></exception>
    private  void _tcpServerSendHandle_RecievedEvent(object? sender, byte[] e)
    {
        if (_cancellationTokenSource == null) return;

        _lgEquipHandle.Equip = _equipInfo;

        var equip = _equipInfo.Adapt<LgHkEquipDto>();
        equip.Data = e;
        _lgEquipHandle.ParseData(equip,_cancellationTokenSource.Token);

      
        // 处理数据
        return;
    }

    /// <summary>
    /// 数据接收事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <exception cref="NotImplementedException"></exception>
    private void _tcpServerReceiveHandle_RecievedEvent(object? sender, byte[] e)
    {
        if (_cancellationTokenSource == null) return;

        _lgEquipHandle.Equip = _equipInfo;

        var equip = _equipInfo.Adapt<LgHkEquipDto>();
        equip.Data = e;
        _lgEquipHandle.ParseData(equip, _cancellationTokenSource.Token);


        // 处理数据
        return;
    }

    /// <summary>
    /// 客户端请求事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <exception cref="NotImplementedException"></exception>
    private void _tcpServerSendHandle_ConnectionRequestEvent(object? sender, System.Net.Sockets.Socket e)
    {
        _tcpServerSendHandle.AddAccept(e);
    }

    public void Dispose()
    {
        return;
    }

    public bool GetConnection()
    {
        return _tcpState== LgTcpState.Connected ;
    }
    /// <summary>
    /// 获取设备信息
    /// </summary>
    /// <returns></returns>
    public LgHkEquipDto GetEquipInfo()
    {
      
        return _equipInfo;
    }

    public bool GetOperationStatus()
    {
        return _status;
    }
    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="group"></param>
    /// <param name="tags"></param>
    /// <returns></returns>
    public async Task<bool> Init(LgHkEquipDto group, IEnumerable<EquipTagDto> tags = null)
    {
        try
        {
            _equipInfo = group;
            // 解析ipaddress
            var ips = group.IPAddress.Split(":");
            if (ips.Length != 2)
            {
                return false;
            }

            var sendPort = group.ReadDirection.To<int>();
            if (sendPort == 0)
            {
                return false;
            }

            _lgEquipHandle = _provider.GetRequiredKeyedService<LgHandleBase>(_equipInfo.EquipType);
            // 设定访问值
            _lgEquipHandle.Api.RemoteApiUrl = _provider.GetService<IConnectDataService>()?.AddressConfig.ApiUrl;
            _lgEquipHandle.Equip = _equipInfo;
            if (_lgEquipHandle != null)
            {
                _lgEquipHandle.SendMsgEvent -= Handle_SendMsgEvent;
                _lgEquipHandle.SendMsgEvent += Handle_SendMsgEvent;
            }
            OnConnectStatusChanged.Invoke(this, new ConnectStatusEventArgs
            {
                Connect = false,
                IsSuccess = true,
                Message = _equipInfo.Remark
            });

        }
        catch(Exception ex)
        {
            _equipInfo.Remark = $"{_equipInfo.ToString()} 初始化失败,原因：{ex.Message}";
            OnConnectStatusChanged.Invoke(this, new ConnectStatusEventArgs
            {
                Connect = false,
                IsSuccess = true,
                Message= _equipInfo.Remark
            });
            return false;
        }
        
        return true;
    }
    /// <summary>
    /// 处理消息
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Handle_SendMsgEvent(object? sender, (LgMsgInfo,LgHkEquipDto) e)
    {
       
        _equipInfo.Value = $"command:{e.Item1.Command} status:{e.Item2.EquipStatus} obj:{e.Item2.Obj}";

        
        // 是否连通  Connected Connecting
        _equipInfo.Remark = e.Item2.Remark;

        _equipInfo.EquipStatus = e.Item2.EquipStatus;

        _equipInfo.Action = e.Item2.Action;

        _equipInfo.Mode = e.Item2.Mode;

        _equipInfo.ExplainData = e.Item2.ExplainData;
       
        _equipInfo.ReadTime = e.Item2.ReadTime;
        // 不发送直接退出
        if (!e.Item1.IsSend) return;
        if (_tcpState == LgTcpState.Connected)
        {
            Task.Run(async () =>
            {
                var msg=_lgEquipHandle.AssambleMsg(e.Item1);
                // 发两次就够了
                var result = await _tcpServerSendHandle.Send(msg);
                if (!result)
                {
                    result = await _tcpServerSendHandle.Send(msg);
                }
                _logService.LogHeart($"Send:{e.Item2.Num}, {e.Item1.Command}: {msg}");
            }, _cancellationTokenSource.Token);

        }
    }

    public async Task<bool> OperationStart()
    {
        _cancellationTokenSource = new CancellationTokenSource();
        var ips = _equipInfo.IPAddress.Split(":");
        _status = true;
        
        var result= await _tcpServerSendHandle.StartListen(ips[0], ips[1].To<int>(),_cancellationTokenSource.Token);

        result=await _tcpServerReceiveHandle.StartListen(ips[0],_equipInfo.ReadDirection.To<int>(),_cancellationTokenSource.Token);

        if (result)
        {
            Task.Factory.StartNew(async () =>
            {
                while (true)
                {
                    if (_cancellationTokenSource.IsCancellationRequested) break;
                    if (_tcpState == LgTcpState.Connected)
                    {
                        _lgEquipHandle.SyncStatus(new LgMsgInfo
                        {
                            ObjID="1A30103"
                            
                        });
                    }
                    await Task.Delay(60000);
                }
               
            }, _cancellationTokenSource.Token);
        }
        return result;
    }

    public async Task<bool> OperationStop()
    {
        _cancellationTokenSource?.Cancel();
        _status = false;
        _tcpServerSendHandle.CloseServer();
        _tcpServerReceiveHandle.CloseServer();

        OnConnectStatusChanged.Invoke(this, new ConnectStatusEventArgs
        {
            Connect = false,
            IsSuccess = true,
        });
        return true;
    }

    public async Task<bool> WriteRequest(OperationWriteCommand writeInfo)
    {
        // 处理消息
        // _factory.Handle_SendMsgEvent(this, e);

        if (writeInfo.Value.IsNullOrEmpty()) return true;
        var datas = writeInfo.Value.Split('*');
        if (datas.Length > 1)
        {
            var command = datas[0];
            var body = datas[1];

            if (command == "133")
            {
                _lgEquipHandle.ReStart(new LgMsgInfo
                {
                    Body = body

                });
            }
            else if (command == "129")
            {
                _lgEquipHandle.Stop(new LgMsgInfo
                {
                    Body = body
                });
            }
        }
        return true;
    }
}
